package nio;

import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FileChannelTest {
    public static String dir = "./files/channel";

    /**
     * FileChannel配合缓冲区实现文件复制的功能
     * @throws IOException
     */
    @Test
    public void test1() throws IOException {
        FileInputStream in= new FileInputStream(new File(dir + "/file1"));
        FileOutputStream out = new FileOutputStream(new File( dir+"/file2"));
        FileChannel inChannel = in.getChannel();
        FileChannel outChannel = out.getChannel();
        ByteBuffer buf = ByteBuffer.allocate(48);
        while (inChannel.read(buf) != -1) {
            buf.flip();
            outChannel.write(buf);
            buf.clear();
        }
    }

    /**
     * 使用内存映射文件的方式实现文件复制的功能(直接操作缓冲区)：
     * 相比普通文件读取，不需要把文件先读取到内核缓存区内存再拷贝到用户内存再进行读取，而是将内核缓冲区的内存和用户缓冲区的内存做了一个地址映射
     * @throws IOException
     */
    @Test
    public void test2() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get(dir + "/file1"), StandardOpenOption.READ);
        //注意此处要传入StandardOpenOption.READ哦，不然会报NonReadableChannelException异常
        FileChannel outChannel = FileChannel.open(Paths.get(dir + "/file2"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);
        MappedByteBuffer inBuf = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
        MappedByteBuffer outBuf = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());
        byte[] dst = new byte[inBuf.limit()];
        inBuf.get(dst);
        System.out.println(dst);
        outBuf.put(dst);
    }


    /**
     * 使用通道transfer()方法进行文件复制
     * @throws IOException
     */
    @Test
    public void test3() throws IOException {
        FileChannel inChannel = FileChannel.open(Paths.get(dir + "/file1"), StandardOpenOption.READ);
        FileChannel outChannel = FileChannel.open(Paths.get(dir + "/file2"), StandardOpenOption.WRITE);
        inChannel.transferTo(0, inChannel.size(), outChannel);
    }


}
